Skip to main content

04 Writing User Stories for APIs

Introduction

This document provides a specialised framework for writing clear, consistent, and testable user stories for API development in Jira. APIs have unique characteristics that require specific considerations in story writing, including endpoints, request/response formats, authentication, error handling, and integration patterns.

Whether you're a Business Analyst, API Designer, Backend Developer, QA Engineer, or Integration Specialist, this guide will help you create API stories that drive clarity, reduce ambiguity, and ensure robust API implementations.

What You'll Learn

By following this guide, you will learn:

  • ✅ How to structure API user stories with API-specific components
  • ✅ How to write acceptance criteria for endpoints, methods, and payloads
  • ✅ Best practices for API authentication, authorisation, and security
  • ✅ How to handle API errors, validation, and edge cases
  • ✅ Techniques for documenting request/response contracts
  • ✅ How to address API versioning, rate limiting, and performance
  • ✅ Templates and examples specific to API development

Key Principles

  • Contract-first – Define API contracts clearly before implementation
  • Security by design – Authentication and authorisation are not optional
  • Error handling – Comprehensive error responses are essential
  • Versioning – Plan for API evolution and backward compatibility
  • Documentation – API stories must include clear request/response examples
  • Testability – ACs must enable both manual and automated API testing

1. Purpose of API User Stories

An API user story expresses a requirement from the perspective of an API consumer (client application, system, or service), describing:

  • What API functionality is needed
  • Why it is needed
  • How it creates value for the consuming system

API user stories differ from UI stories in that they focus on:

  • Data exchange rather than user interaction
  • System-to-system communication rather than human-computer interaction
  • Contract definitions (request/response formats) rather than visual design
  • Integration patterns rather than workflow steps

Why API Stories Matter

Well-written API stories:

  • Enable integration – Clear contracts allow other systems to integrate effectively
  • Reduce integration time – Detailed specifications prevent back-and-forth clarification
  • Ensure consistency – Standardised patterns across API endpoints
  • Facilitate testing – Testable ACs enable automated API testing
  • Support documentation – Stories become the foundation for API documentation

2. Core Structure for API Stories

Each API user story should follow this template:

As a [API consumer role]
I want to [API action/operation]
So that [business value/integration benefit]

Guidelines for Each Line

AS A… (API Consumer Role)

The role represents who or what consumes the API:

  • Client applications – "As a mobile application"
  • External systems – "As a third-party billing system"
  • Internal services – "As a microservice"
  • System actors – "As a scheduled batch job"
  • API consumers – "As an API client"

Examples:

  • ✅ "As a mobile application"
  • ✅ "As a third-party integration service"
  • ✅ "As a scheduled billing processor"
  • ❌ "As a developer" (too vague)
  • ❌ "As a user" (APIs don't have direct users)

I WANT… (API Action/Operation)

Describe the API operation clearly:

  • Use HTTP method terminology when appropriate
  • Focus on the data operation, not implementation
  • Be specific about what data is exchanged

Good examples:

  • ✅ "I want to retrieve enquiry details by ID"
  • ✅ "I want to create a new enquiry via API"
  • ✅ "I want to update enquiry status"
  • ✅ "I want to search enquiries with filters"

Poor examples:

  • ❌ "I want an API endpoint" (too vague)
  • ❌ "I want to call the database" (too technical)
  • ❌ "I want a REST API" (implementation detail)

SO THAT… (Business Value/Integration Benefit)

Explain why the API is needed:

  • Focus on integration benefits
  • Describe business value enabled
  • Explain system-to-system value

Examples:

  • ✅ "So that the mobile app can display enquiry details"
  • ✅ "So that external systems can create enquiries automatically"
  • ✅ "So that billing systems can retrieve invoice data"
  • ✅ "So that real-time status updates can be synchronized"

3. HTTP Methods

Understanding HTTP methods is crucial for designing RESTful APIs. Each method has a specific purpose and semantic meaning that should be respected to ensure API consistency and predictability.

GET

Definition: GET is used to retrieve data from a server. It is a safe and idempotent method, meaning it should not modify server state and can be called multiple times with the same result.

When to Use:

  • Retrieving a single resource by ID: GET /api/v1/enquiries/{id}
  • Listing multiple resources: GET /api/v1/enquiries
  • Searching or filtering resources: GET /api/v1/enquiries?status=AUTHORISED
  • Reading data without side effects

Characteristics:

  • ✅ Safe – Does not modify server state
  • ✅ Idempotent – Multiple identical requests have the same effect
  • ✅ Cacheable – Responses can be cached
  • ❌ Should not have a request body (though technically allowed)
  • ❌ Should not be used for operations that change data

Example:

GET /api/v1/enquiries/12345 HTTP/1.1
Host: api.example.com
Authorisation: Bearer {api_key}

POST

Definition: POST is used to create new resources or perform actions that result in state changes. It is not idempotent – calling it multiple times may create multiple resources.

When to Use:

  • Creating a new resource: POST /api/v1/enquiries
  • Performing actions that don't fit other methods: POST /api/v1/enquiries/{id}/complete
  • Submitting forms or data
  • Triggering operations with side effects

Characteristics:

  • ❌ Not safe – Modifies server state
  • ❌ Not idempotent – Multiple calls may create multiple resources
  • ✅ Can have a request body
  • ✅ Returns 201 Created with Location header for new resources
  • ✅ Returns 200 OK for actions without resource creation

Example:

POST /api/v1/enquiries HTTP/1.1
Host: api.example.com
authorisation: Bearer {api_key}
Content-Type: application/json

{
"customerId": "CUST001",
"vehicleRegistration": "AB12 CDE",
"description": "MOT Test"
}

PUT

Definition: PUT is used to replace an entire resource or create it if it doesn't exist. It is idempotent – calling it multiple times with the same data has the same effect.

When to Use:

  • Updating an entire resource: PUT /api/v1/enquiries/{id}
  • Creating a resource with a specific ID: PUT /api/v1/enquiries/{id}
  • Full resource replacement (not partial updates)

Characteristics:

  • ❌ Not safe – Modifies server state
  • ✅ Idempotent – Multiple identical requests have the same effect
  • ✅ Can have a request body
  • ✅ Must include all fields (full replacement)
  • ✅ Returns 200 OK if resource exists, 201 Created if new resource created

Example:

PUT /api/v1/enquiries/12345 HTTP/1.1
Host: api.example.com
authorisation: Bearer {api_key}
Content-Type: application/json

{
"enquiryId": "12345",
"status": "COMPLETED",
"customerId": "CUST001",
"vehicleRegistration": "AB12 CDE",
"completedAt": "2025-01-15T14:30:00Z"
}

PATCH

Definition: PATCH is used to partially update a resource. It applies modifications to an existing resource without replacing the entire resource. It should be idempotent when possible.

When to Use:

  • Partial updates to a resource: PATCH /api/v1/enquiries/{id}
  • Updating specific fields without sending the entire resource
  • When you only want to change a few fields

Characteristics:

  • ❌ Not safe – Modifies server state
  • ✅ Should be idempotent (when possible)
  • ✅ Can have a request body
  • ✅ Only includes fields to be updated
  • ✅ Returns 200 OK with updated resource

Example:

PATCH /api/v1/enquiries/12345 HTTP/1.1
Host: api.example.com
authorisation: Bearer {api_key}
Content-Type: application/json

{
"status": "COMPLETED",
"completedAt": "2025-01-15T14:30:00Z"
}

DELETE

Definition: DELETE is used to remove a resource from the server. It is idempotent – deleting a resource that doesn't exist should still return success (or 404 Not Found).

When to Use:

  • Deleting a resource: DELETE /api/v1/enquiries/{id}
  • Removing a resource permanently
  • Soft deletes (marking as deleted) can also use DELETE

Characteristics:

  • ❌ Not safe – Modifies server state
  • ✅ Idempotent – Deleting a non-existent resource should be safe
  • ❌ Should not have a request body
  • ✅ Returns 200 OK or 204 No Content on success
  • ✅ Returns 404 Not Found if resource doesn't exist (optional)

Example:

DELETE /api/v1/enquiries/12345 HTTP/1.1
Host: api.example.com
authorisation: Bearer {api_key}

Method Selection Guide

OperationMethodExample
Retrieve single resourceGETGET /api/v1/enquiries/{id}
List resourcesGETGET /api/v1/enquiries
Create new resourcePOSTPOST /api/v1/enquiries
Replace entire resourcePUTPUT /api/v1/enquiries/{id}
Partial updatePATCHPATCH /api/v1/enquiries/{id}
Delete resourceDELETEDELETE /api/v1/enquiries/{id}
Action/OperationPOSTPOST /api/v1/enquiries/{id}/complete

💡 Tip: When in doubt between PUT and PATCH, use PATCH for partial updates. Use PUT only when you're replacing the entire resource.


4. HTTP Status Codes

HTTP status codes communicate the result of an API request. Using appropriate status codes is essential for clear API contracts and proper error handling. Status codes are grouped into five categories:

2xx Success

These codes indicate that the request was successfully received, understood, and processed.

200 OK

  • Use when: Request succeeded
  • Common for: GET, PUT, PATCH requests
  • Response: Usually includes response body with data

Example:

200 OK
{
"enquiryId": "12345",
"status": "AUTHORISED"
}

201 Created

  • Use when: New resource was successfully created
  • Common for: POST requests that create resources
  • Response: Should include Location header with URL of new resource
  • Response body: Usually includes the created resource

Example:

201 Created
Location: /api/v1/enquiries/12345
{
"enquiryId": "12345",
"status": "CREATED"
}

204 No Content

  • Use when: Request succeeded but no content to return
  • Common for: DELETE requests, or updates that don't need response body
  • Response: No response body

Example:

204 No Content
(Empty body)

4xx Client Error

These codes indicate that the client made an error (e.g., bad request, unauthorized, not found).

400 Bad Request

  • Use when: Request is malformed or invalid
  • Common causes: Missing required fields, invalid data format, validation errors
  • Response: Should include error details explaining what's wrong

Example:

400 Bad Request
{
"error": "Bad Request",
"message": "Validation failed",
"code": "VALIDATION_ERROR",
"details": [
{
"field": "customerId",
"message": "customerId is required"
}
]
}

401 Unauthorized

  • Use when: Authentication is required or failed
  • Common causes: Missing authentication token, invalid credentials, expired token
  • Response: Should include WWW-Authenticate header

Example:

401 Unauthorized
WWW-Authenticate: Bearer
{
"error": "Unauthorized",
"message": "Valid API key required",
"code": "AUTH_REQUIRED"
}

403 Forbidden

  • Use when: Client is authenticated but not authorized for the action
  • Common causes: Insufficient permissions, role restrictions
  • Difference from 401: Client is authenticated but lacks permission

Example:

403 Forbidden
{
"error": "Forbidden",
"message": "You do not have permission to delete enquiries",
"code": "INSUFFICIENT_PERMISSIONS"
}

404 Not Found

  • Use when: Requested resource does not exist
  • Common for: GET, PUT, PATCH, DELETE requests for non-existent resources
  • Response: Should indicate which resource was not found

Example:

404 Not Found
{
"error": "Not Found",
"message": "Enquiry with ID 99999 not found",
"code": "ENQUIRY_NOT_FOUND"
}

409 Conflict

  • Use when: Request conflicts with current state of resource
  • Common causes: Duplicate creation, version conflicts, concurrent modifications
  • Response: Should explain the conflict

Example:

409 Conflict
{
"error": "Conflict",
"message": "Enquiry with this ID already exists",
"code": "DUPLICATE_ENQUIRY"
}

422 Unprocessable Entity

  • Use when: Request is well-formed but semantically incorrect
  • Common causes: Business rule violations, logical errors
  • Difference from 400: Request syntax is valid but business logic fails

Example:

422 Unprocessable Entity
{
"error": "Unprocessable Entity",
"message": "Cannot complete enquiry in current status",
"code": "INVALID_STATUS_TRANSITION"
}

429 Too Many Requests

  • Use when: Client has exceeded rate limit
  • Response: Should include Retry-After header indicating when to retry
  • Response: Should include rate limit headers (X-RateLimit-*)

Example:

429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Please retry after 60 seconds",
"code": "RATE_LIMIT_EXCEEDED"
}

5xx Server Error

These codes indicate that the server encountered an error and could not fulfill the request.

500 Internal Server Error

  • Use when: Unexpected server error occurred
  • Common causes: Unhandled exceptions, database errors, system failures
  • Response: Should not expose internal implementation details
  • Note: Should be logged for investigation

Example:

500 Internal Server Error
{
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"code": "INTERNAL_ERROR",
"requestId": "req-12345"
}

502 Bad Gateway

  • Use when: Server acting as gateway received invalid response from upstream server
  • Common causes: Upstream service unavailable, timeout, invalid response
  • Use in: API gateway or proxy scenarios

Example:

502 Bad Gateway
{
"error": "Bad Gateway",
"message": "Upstream service unavailable",
"code": "UPSTREAM_ERROR"
}

503 Service Unavailable

  • Use when: Server is temporarily unavailable
  • Common causes: Maintenance, overload, temporary outage
  • Response: Should include Retry-After header if known

Example:

503 Service Unavailable
Retry-After: 300
{
"error": "Service Unavailable",
"message": "Service is temporarily unavailable. Please retry later",
"code": "SERVICE_UNAVAILABLE"
}

504 Gateway Timeout

  • Use when: Server acting as gateway did not receive timely response from upstream
  • Common causes: Upstream service timeout, slow response
  • Use in: API gateway or proxy scenarios

Example:

504 Gateway Timeout
{
"error": "Gateway Timeout",
"message": "Upstream service did not respond in time",
"code": "UPSTREAM_TIMEOUT"
}

Status Code Selection Guide

ScenarioStatus CodeMethod
Successfully retrieved resource200GET
Successfully created resource201POST
Successfully updated resource200 or 204PUT, PATCH
Successfully deleted resource200 or 204DELETE
Invalid request format400Any
Missing/invalid authentication401Any
Insufficient permissions403Any
Resource not found404GET, PUT, PATCH, DELETE
Resource conflict409POST, PUT, PATCH
Validation failed422POST, PUT, PATCH
Rate limit exceeded429Any
Server error500Any
Service unavailable503Any

💡 Tip: Always include an error response body with 4xx and 5xx status codes. Include an error code, human-readable message, and optionally request ID for tracing.


5. Summary Section

The Summary Section for API stories provides brief bullet points that summarize what the API endpoint will deliver. It acts as a quick reference for developers, testers, and stakeholders to understand the intent of the story without reading the full acceptance criteria.

This section should answer the question:

"What will be different once this API endpoint is delivered?"

Purpose of the Summary Section

  • Communicates API intent at a glance
  • Helps reviewers quickly understand scope
  • Supports faster refinement and estimation
  • Reduces misinterpretation of detailed acceptance criteria
  • Acts as a sanity check before development begins

Guidelines for Writing the Summary

  • Use simple, non-technical language
  • Focus on outcomes, not implementation
  • Keep each bullet point brief and clear
  • Use bullet points (not numbered lists)
  • Avoid edge cases and exceptions (covered in ACs)
  • Typically include 3–6 high-level bullet points
  • Ensure alignment with the As a / I want / So that statement

What to Include in Summary

The Summary should include brief bullet points covering:

  • API endpoint – HTTP method and endpoint path
  • Primary functionality – What the API does
  • Authentication/authorisation – Security requirements
  • Key data operations – What data is exchanged
  • Integration context – Who consumes this API
  • Important constraints – Rate limits, versioning, etc.

What to Avoid

  • Technical design or solution details
  • Database or infrastructure specifics
  • Error handling scenarios (covered in Acceptance Criteria)
  • Overlapping or duplicate points
  • Detailed request/response structures (covered in API Contract)

Example Summary

  • Create GET endpoint /api/v1/enquiries/{id} to retrieve enquiry details
  • Implement authentication using API key
  • Return enquiry data in JSON format with standard structure
  • Handle not found (404) and unauthorized (401) errors
  • Support integration with mobile application and third-party systems

Quality Checklist

A good summary should:

  • Be readable in under 30 seconds
  • Clearly describe the API endpoint and its purpose
  • Match the acceptance criteria
  • Contain no technical jargon
  • Reflect business/integration intent

Analyst Tip

If the summary cannot be clearly written in 3–6 bullet points, the story is likely:

  • Too large
  • Poorly defined
  • Missing clarity

In such cases, revisit the scope or split the story before refinement.


6. Acceptance Criteria for APIs

API acceptance criteria must cover:

  • Request validation – Input validation and error responses
  • Response format – Structure, status codes, headers
  • Authentication/authorisation – Security validation
  • Error handling – All error scenarios
  • Edge cases – Boundary conditions, null handling
  • Performance – Response times, throughput

BDD Format for APIs

KeywordPurposeAPI Example
GivenPreconditions or API state"Given an enquiry exists with ID 12345"
WhenAPI request is made"When a GET request is made to /api/v1/enquiries/12345"
ThenExpected API response"Then the API returns status 200 with enquiry JSON"
AndAdditional conditions"And the response includes all required fields"

API-Specific AC Patterns

Successful Request

Given an enquiry exists with ID 12345
And the API client has valid authentication
When a GET request is made to /api/v1/enquiries/12345
Then the API returns status code 200
And the response body contains enquiry data in JSON format
And the response includes Content-Type: application/json header

Authentication Failure

Given an API request is made
When the request does not include a valid API key
Then the API returns status code 401
And the response body contains error message "Unauthorized"
And the response includes WWW-Authenticate header

Resource Not Found

Given no enquiry exists with ID 99999
And the API client has valid authentication
When a GET request is made to /api/v1/enquiries/99999
Then the API returns status code 404
And the response body contains error message "Enquiry not found"

Validation Error

Given the API client has valid authentication
When a POST request is made to /api/v1/enquiries
And the request body is missing required field "customerId"
Then the API returns status code 400
And the response body contains validation error details
And the error includes field name and error message

Rate Limiting

Given the API client has made 100 requests in the last minute
And the rate limit is 100 requests per minute
When another request is made
Then the API returns status code 429
And the response includes Retry-After header
And the response body indicates rate limit exceeded

7. Example of a Fully Structured API User Story

User Story

As a mobile application
I want to retrieve enquiry details by ID via API
So that users can view enquiry information on their mobile devices

Summary

  • Create GET endpoint /api/v1/enquiries/{id} to retrieve enquiry by ID
  • Implement API key authentication
  • Return enquiry data in standardized JSON format
  • Handle authentication, authorisation, and not found errors
  • Support mobile application integration requirements

Acceptance Criteria

AC1 – Successful enquiry retrieval

Given an enquiry exists with ID 12345
And the enquiry status is AUTHORISED
And the API client has a valid API key
When a GET request is made to /api/v1/enquiries/12345
Then the API returns HTTP status code 200
And the response Content-Type is application/json
And the response body contains JSON:
{
"enquiryId": "12345",
"status": "AUTHORISED",
"customerId": "CUST001",
"vehicleRegistration": "AB12 CDE",
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-01-15T14:20:00Z"
}

AC2 – Authentication failure

Given an API request is made to /api/v1/enquiries/12345
When the request does not include authorisation header
Or the API key is invalid
Or the API key has expired
Then the API returns HTTP status code 401
And the response body contains:
{
"error": "Unauthorized",
"message": "Valid API key required",
"code": "AUTH_REQUIRED"
}
And the response includes WWW-Authenticate header

AC3 – Resource not found

Given no enquiry exists with ID 99999
And the API client has valid authentication
When a GET request is made to /api/v1/enquiries/99999
Then the API returns HTTP status code 404
And the response body contains:
{
"error": "Not Found",
"message": "Enquiry with ID 99999 not found",
"code": "ENQUIRY_NOT_FOUND"
}

AC4 – Invalid enquiry ID format

Given the API client has valid authentication
When a GET request is made to /api/v1/enquiries/invalid-id
Then the API returns HTTP status code 400
And the response body contains validation error:
{
"error": "Bad Request",
"message": "Invalid enquiry ID format",
"code": "INVALID_ID_FORMAT"
}

AC5 – Response time performance

Given an enquiry exists with ID 12345
And the API client has valid authentication
When a GET request is made to /api/v1/enquiries/12345
Then the API responds within 200 milliseconds
And the response time is consistent under normal load

AC6 – CORS headers for mobile app

Given a GET request is made to /api/v1/enquiries/12345
When the request includes Origin header from mobile app domain
Then the response includes CORS headers:
- Access-Control-Allow-Origin: [mobile app domain]
- Access-Control-Allow-Methods: GET, OPTIONS
- Access-Control-Allow-Headers: authorisation, Content-Type

API Contract

Endpoint: GET /api/v1/enquiries/{id}

Authentication: API Key (Bearer token in authorisation header)

Request:

GET /api/v1/enquiries/12345 HTTP/1.1
Host: api.example.com
authorisation: Bearer {api_key}
Accept: application/json

Response (200 OK):

{
"enquiryId": "12345",
"status": "AUTHORISED",
"customerId": "CUST001",
"customerName": "ABC Fleet Ltd",
"vehicleRegistration": "AB12 CDE",
"vehicleMake": "Ford",
"vehicleModel": "Transit",
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-01-15T14:20:00Z",
"jobLines": [
{
"lineId": "JL001",
"description": "MOT Test",
"status": "COMPLETED",
"amount": 54.99
}
]
}

Error Responses:

  • 401 Unauthorized – Missing or invalid API key
  • 404 Not Found – Enquiry ID doesn't exist
  • 400 Bad Request – Invalid ID format
  • 429 Too Many Requests – Rate limit exceeded
  • 500 Internal Server Error – Server error

Dependencies

  • Story ABC-123: API authentication service
  • Story ABC-124: Enquiry data access layer
  • External: API gateway configuration

Notes

  • This endpoint is part of API version 1
  • Rate limit: 100 requests per minute per API key
  • Response caching: 60 seconds for successful responses
  • Related design document: [Link to API design doc]
  • Postman collection: [Link to Postman collection]

Note: This story must comply with the project's Definition of Done and API standards.


8. API-Specific Considerations

Authentication & authorisation

Every API story must address:

  • Authentication method – API key, OAuth, JWT, Basic Auth
  • authorisation levels – What permissions are required
  • Token validation – How tokens are validated
  • Token expiration – Handling expired tokens

AC Example:

Given an API request is made
When the request includes a valid JWT token
And the token has "enquiry:read" permission
Then the API processes the request
And when the token lacks required permission
Then the API returns status 403 Forbidden

Request Validation

API stories must cover:

  • Required fields – What fields are mandatory
  • Field formats – Data type, format, constraints
  • Field lengths – Min/max length validation
  • Enum values – Valid value sets

AC Example:

Given a POST request to /api/v1/enquiries
When the request body is missing required field "customerId"
Then the API returns status 400
And the error response lists all missing required fields
And when a field has invalid format (e.g., invalid date)
Then the API returns status 400 with field-specific error

Response Format Standards

Define:

  • Status codes – HTTP status code usage
  • Response structure – Consistent JSON structure
  • Error format – Standardized error response format
  • Headers – Required response headers

AC Example:

Given a successful API request
Then the response includes:
- Standard HTTP status code (200, 201, etc.)
- Content-Type: application/json header
- Consistent JSON structure with data/error wrapper
- Timestamp in ISO 8601 format

Error Handling

Cover all error scenarios:

  • 4xx Client Errors – Bad requests, unauthorized, not found, etc.
  • 5xx Server Errors – Internal errors, service unavailable
  • Error response format – Consistent error structure
  • Error codes – Application-specific error codes

AC Example:

Given an error occurs during API processing
When the error is a client error (validation, not found)
Then the API returns appropriate 4xx status code
And the error response includes:
- error: error type
- message: human-readable message
- code: application error code
- details: additional error details (if applicable)

Rate Limiting

Define:

  • Rate limits – Requests per time period
  • Rate limit headers – X-RateLimit-* headers
  • Rate limit exceeded response – 429 status handling

AC Example:

Given the API has rate limit of 100 requests per minute
When 100 requests are made within one minute
And another request is attempted
Then the API returns status 429
And the response includes:
- Retry-After header with seconds to wait
- X-RateLimit-Limit header
- X-RateLimit-Remaining header
- X-RateLimit-Reset header

API Versioning

Address:

  • Version strategy – URL versioning, header versioning
  • Backward compatibility – Breaking vs non-breaking changes
  • Deprecation – How deprecated versions are handled

AC Example:

Given API version 2 is released
When a request is made to version 1 endpoint
Then the API continues to support version 1
And when version 1 is deprecated
Then the API returns status 410 Gone
And includes deprecation notice in response

Pagination

For list endpoints:

  • Pagination method – Offset-based, cursor-based
  • Page size limits – Min/max page sizes
  • Pagination metadata – Total count, next/prev links

AC Example:

Given multiple enquiries exist
When a GET request is made to /api/v1/enquiries
Then the API returns paginated results
And the response includes:
- data: array of enquiries
- pagination: { page, pageSize, total, totalPages }
- links: { first, last, next, prev }

9. API Story Anti-Patterns

Missing Authentication

❌ Bad Example:

As a client application
I want to retrieve enquiry data
So that I can display it
(Missing authentication requirements)

✅ Good Example:

As a mobile application
I want to retrieve enquiry data via authenticated API
So that users can securely view enquiry information
(Includes authentication ACs)

Vague Endpoint Definition

❌ Bad Example:

I want an API to get data
(No endpoint, method, or format specified)

✅ Good Example:

I want to retrieve enquiry details via GET /api/v1/enquiries/{id}
So that the mobile app can display enquiry information
(Includes specific endpoint and method)

Missing Error Handling

❌ Bad Example:

Story only covers happy path, no error scenarios

✅ Good Example:

Story includes ACs for:

  • Authentication errors
  • Validation errors
  • Not found errors
  • Server errors

No Request/Response Examples

❌ Bad Example:

Story describes endpoint but provides no contract examples

✅ Good Example:

Story includes:

  • Request example with headers
  • Response example (success)
  • Error response examples
  • Postman collection reference

10. How to Split Large API Stories

API stories can be split by:

TechniqueDescriptionExample
HTTP MethodsSplit by operation typeGET, POST, PUT, DELETE
Resource endpointsSplit by resource type/enquiries, /vehicles, /customers
AuthenticationSplit auth from functionalityAuth setup, then endpoints
Error handlingSplit happy path from errorsSuccess cases, then error cases
API versionsSplit by versionv1 endpoints, then v2 endpoints
Bulk vs singleSplit by operation scopeSingle item, then bulk operations

Example: "Enquiry Management API" can be split into:

  1. Story 1: GET /api/v1/enquiries/{id} – Retrieve single enquiry
  2. Story 2: GET /api/v1/enquiries – List/search enquiries
  3. Story 3: POST /api/v1/enquiries – Create enquiry
  4. Story 4: PUT /api/v1/enquiries/{id} – Update enquiry
  5. Story 5: DELETE /api/v1/enquiries/{id} – Delete enquiry

11. Template for Creating API User Stories

Use this template for new API stories:

## User Story

As a [API consumer - e.g., mobile application, third-party system]
I want to [API operation - e.g., retrieve enquiry details by ID]
So that [business value - e.g., users can view enquiry information]

## Summary

- [Brief bullet point 1 - e.g., Create GET endpoint /api/v1/enquiries/{id}]
- [Brief bullet point 2 - e.g., Implement API key authentication]
- [Brief bullet point 3 - e.g., Return enquiry data in JSON format]
- [Brief bullet point 4 - e.g., Handle authentication and not found errors]

## Acceptance Criteria

### AC1 - [Brief description]

Given [precondition] When [API request is made] Then [expected response] And [additional conditions]


### AC2 - [Brief description]

Given [precondition] When [API request is made] Then [expected response]


## API Contract

**Request:**

[HTTP Method] [Endpoint] HTTP/1.1 [Headers] [Request body if applicable]


**Response (Success):**

```json
{
"example": "response structure"
}

Error Responses:

  • [Status Code] – [Error description]
  • [Status Code] – [Error description]

12. API Story Quality Checklist

Every API story must satisfy:

Story Writing

  • Clear API consumer role (not "user" or "developer")
  • Specific endpoint and HTTP method defined
  • Business value clearly stated
  • Summary section with brief bullet points included

API Contract

  • Endpoint path clearly defined
  • HTTP method specified
  • Request format documented (headers, body)
  • Response format documented (success and errors)
  • Authentication method specified
  • authorisation requirements defined

Acceptance Criteria

  • Happy path covered
  • Authentication failure covered
  • authorisation failure covered (if applicable)
  • Validation errors covered
  • Not found errors covered
  • Server errors covered
  • Rate limiting covered (if applicable)
  • Response time requirements defined

Integration Considerations

  • Upstream dependencies identified
  • Downstream impacts considered
  • API versioning strategy defined
  • Backward compatibility addressed
  • CORS requirements specified (if web clients)

Documentation

  • Request example provided
  • Response example provided
  • Error response examples provided
  • Postman collection or similar reference (if applicable)

13. Conclusion

Well-structured API user stories enable clear integration, reduce development time, and ensure robust API implementations. Following this guide standardizes API story quality across teams and accelerates API delivery.

Key takeaways:

  • Contract-first approach – Define API contracts clearly
  • Security is mandatory – Authentication and authorisation are not optional
  • Comprehensive error handling – Cover all error scenarios
  • Clear examples – Request/response examples are essential
  • Testability – ACs must enable automated API testing

Use this document as the standard reference for all API story creation in Jira.